#coding:gbk

import os
import os.path
import smartcard as _sc

ROOT_DIR = "z:\\apps\\Tools\\PBOC3_TEST"

PRIVATE_CMD = "\t\tPRIVATE"
GP_AID          = _sc.str2bytes("A0 00 00 00 03 00 00 00")
PSE_AID         = "1PAY.SYS.DDF01"
PPSE_AID        = "2PAY.SYS.DDF01"
PBOC_APP_AID    = _sc.str2bytes("A0 00 00 03 33 01 01")

g_select_flag   = False

def select(cmdApdu, rspApdu):
    global g_select_flag
    aid = cmdApdu[5:5 + ord(cmdApdu[4])]
    appName = ""
    g_select_flag = True
    if aid == PSE_AID:
        appName = "PSE"
    elif aid == PPSE_AID:
        appName = "PPSE"
    elif aid == PBOC_APP_AID:
        appName = "PBOC"
    elif aid == GP_AID:
        g_select_flag = False
        return
    else:
        pass
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "SELECT %s %s" %(appName, status)

def external_authenticate(cmdApdu, rspApdu):
    global g_select_flag
    if not g_select_flag:
        return
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "EXTERNAL AUTHENTICATE %s" %(status)

def internal_authenticate(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "EXTERNAL AUTHENTICATE %s" %(status)

def read_record(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "READ RECORD %s" %(status)

def gpo(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "GPO %s" %(status)

def pin_verify(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "PIN VERIFY %s" %(status)

def get_ac_type(p1):
    if p1 & 0xC0 == 0x00:
        the_type = "AAC"
    elif p1 & 0xC0 == 0x40:
        the_type = "TC"
    elif p1 & 0xC0 == 0x80:
        the_type = "ARQC"
    else:
        the_type = "INVALID"
    return  the_type


def gac(cmdApdu, rspApdu):
    p1 = ord(cmdApdu[2])
    req_type = get_ac_type(p1)
    rsp_type = ""
    cda_flag = " CDA" if (p1 & 0x10) == 0x10 else ""
    if rspApdu[-2:] == '\x90\x00':
        status = "Y"
        p1 = ord(rspApdu[2])
        rsp_type = get_ac_type(p1)
    else:
        status = "N"
    print "GAC [%s%s] [%s] %s" %(req_type, cda_flag, rsp_type, status)

def get_data(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "GET DATA %s" %(status)

def app_block(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "APP BLOCK %s" %(status)

def card_block(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "CARD BLOCK %s" %(status)

def app_unblock(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "APP UNBLOCK %s" %(status)

def pin_change_unblock(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "PIN CHANGE UNBLOCK %s" %(status)

def put_data(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "PUT DATA %s" %(status)

def update_record(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "UPDATE RECORD %s" %(status)

def read_capp_data(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "READ CAPP DATA %s" %(status)

def update_capp_data(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "UPDATE CAPP DATA %s" %(status)

def append_record(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "APPEND RECORD %s" %(status)

def get_trans_prove(cmdApdu, rspApdu):
    status = "Y" if rspApdu[-2:] == '\x90\x00' else "N"
    print "GET TRANS PROVE %s" %(status)

g_dict = {
    "A4" : select,
    "82" : external_authenticate,

    "88" : internal_authenticate,
    "B2" : read_record,
    "A8" : gpo,
    "20" : pin_verify,
    "AE" : gac,
    "CA" : get_data,
    "1E" : app_block,
    "16" : card_block,
    "18" : app_unblock,
    "24" : pin_change_unblock,
    "DA" : put_data,
    "DC" : update_record,

    "B4" : read_capp_data,
    "DE" : update_capp_data,
    "E2" : append_record,
    "5A" : get_trans_prove,
}

def process_cmds(cmds):
    for cmd in cmds:
        if isinstance(cmd, tuple):
            cmdApdu, rspApdu = cmd
            key = cmdApdu[3:5]
            if key in g_dict:
                if key in g_dict:
                    func = g_dict[key]
                    func(_sc.str2bytes(cmdApdu), _sc.str2bytes(rspApdu))
                else:
                    pass
        else:
            print cmd

def get_cmds(fileFullName):
    cmds = []
    with open(fileFullName) as fObj:
        lines = fObj.readlines()
        length = len(lines)
        i = 0
        while i < length:
            line = lines[i].strip()
            if line == "":
                pass
            elif line.startswith("Special Command: Reset"):
                cmds.append("__________RESET")
            elif line.startswith("Send:"):
                cmdApdu = line[6:]
                i += 1
                rspApdu = lines[i].strip()[6:]
                cmds.append((cmdApdu, rspApdu))
            else:
                pass
            i += 1
    return cmds

def main():
    for root, dirs, files in os.walk(ROOT_DIR):
        for fileName in files:
            if fileName.endswith(".txt") and fileName.startswith("V02_P"):
                fileFullName = os.path.join(root, fileName)
                print
                print fileFullName
                cmds = get_cmds(fileFullName)
                process_cmds(cmds)

main()

